package is.progetto1.aritmeticExpression;

import static is.progetto1.aritmeticExpression.Utility.REGEX_VARIABLE;
import is.progetto1.exception.IllegalPropertyException;
import is.progetto1.exception.InvalidVarableException;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.StreamTokenizer;
import java.util.Map;
import java.util.TreeMap;

public final class Context {
	private Map<String, Integer> contex;

	public Context(String url) throws IOException {
		this.contex = new TreeMap<>();
		StreamTokenizer st = new StreamTokenizer(new InputStreamReader(
				new FileInputStream(new File(url))));
		st.resetSyntax();
		st.eolIsSignificant(true);
		st.wordChars('a', 'z');
		st.wordChars('A', 'Z');
		st.parseNumbers();
		st.whitespaceChars('\u0000', ' ');
		String variable = null;
		Integer value = null;
		boolean endLine = false;
		boolean end = false;
		while (!end) {
			switch (st.nextToken()) {
			case StreamTokenizer.TT_EOF:
				if (!endLine) {
					throw new IllegalPropertyException("EOL");
				}
				if (variable == null || value == null) {
					throw new IllegalPropertyException("No variable found");
				}
				this.contex.put(variable, value);
				end = true;
				break;
			case StreamTokenizer.TT_EOL:
				if (!endLine) {
					throw new IllegalPropertyException("EOL");
				}
				if (variable == null || value == null) {
					throw new IllegalPropertyException("No variable found");
				}
				this.contex.put(variable, value);
				endLine = false;
				variable = null;
				value = null;
				break;
			case StreamTokenizer.TT_WORD:
				if (endLine) {
					throw new IllegalPropertyException("EOL");
				}
				if(variable!=null){
					throw new IllegalPropertyException("two variable in same line");
				}
				if (!st.sval.matches(REGEX_VARIABLE)) {
					throw new InvalidVarableException(st.sval + " not allowed");
				}
				variable = st.sval;
				break;
			case StreamTokenizer.TT_NUMBER:
				if (endLine) {
					throw new IllegalPropertyException("EOL");
				}
				value = (int) st.nval;
				endLine = true;
				break;
			default:
				throw new IOException();
			}
		}
	}
	
	public Integer getVariableValue(Variable v){
		Integer res=this.contex.get(v.getName());
		return res;
	}
	
	@Override
	public final int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((contex == null) ? 0 : contex.hashCode());
		return result;
	}

	@Override
	public final boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Context other = (Context) obj;
		if (contex == null) {
			if (other.contex != null)
				return false;
		} else if (!contex.equals(other.contex))
			return false;
		return true;
	}

	@Override
	public final String toString(){
		return contex.toString();
	}
	
}
